package com.qfedu.sign.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.qfedu.sign.common.config.RedisKeyConfig;
import com.qfedu.sign.common.third.JedisUtil;
import com.qfedu.sign.common.vo.R;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;

import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


@Component
public class SignFilter implements GlobalFilter, Ordered {
    //实现过滤处理
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.获取信息，请求和响应
        ServerHttpRequest request=exchange.getRequest();
        ServerHttpResponse response=exchange.getResponse();

        //2.获取请求路径
        String u=request.getURI().getPath();
        //3.验证请求的是否为签到服务
        if(u.startsWith("/sign")){

            //请求的是签到服务
            //4.验证请求是否为签到相关接口
            if(u.contains(".do")){
                boolean isSucc=false;
                //5.获取当前的uid
                if(request.getQueryParams().containsKey("uid")){
                    String uid=request.getQueryParams().get("uid").get(0);
                    //6.校验uid是否为空
                    if(StringUtils.hasLength(uid)) {

                        JedisUtil jedisUtil = new JedisUtil();
                        //7.验证当前用户是否为黑名单
                        if (!jedisUtil.checkField(RedisKeyConfig.SIGN_BKEY, uid)) {

                            //不是黑名单,需要校验或记录请求次数
                            //8.验证当前用户的请求次数的key是否存在
                            if (jedisUtil.exists(RedisKeyConfig.SIGN_REQ_COUNT + uid)) {

                                //9.获取用户的请求次数
                                int c = Integer.parseInt(jedisUtil.getStr(RedisKeyConfig.SIGN_REQ_COUNT + uid));

                                //10.校验请求次数是否超出上限20次
                                if (c + 1 < 20) {

                                    //11.请求次数自增1
                                    jedisUtil.incr(RedisKeyConfig.SIGN_REQ_COUNT + uid);
                                    isSucc = true;//放行
                                } else {

                                    //12.拉黑用户，同时删除请求次数的记录
                                    jedisUtil.addHash(RedisKeyConfig.SIGN_BKEY, uid, "请求次数超过20次");
                                    jedisUtil.delKeys(RedisKeyConfig.SIGN_REQ_COUNT + uid);
                                }
                            } else {

                                //13.第一次（要么真的是第一次，要么是曾经失效）缓存请求次数
                                jedisUtil.addStr(RedisKeyConfig.SIGN_REQ_COUNT + uid, "1", RedisKeyConfig.SIGN_REQ_COUNT_TIME);
                                isSucc = true;
                            }
                        }
                    }
                }

                if(isSucc){
                    //14.放行请求
                    return chain.filter(exchange);
                }else {

                    //15.拦截请求，要么超出限制拉黑，要么就是非法请求
                    //生成响应消息
                    String json= JSON.toJSONString(R.fail("亲，非法请求"));
                    //设置响应信息
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    response.getHeaders().add("Content-Type","application/json;charset=UTF-8");
                    //创建缓存对象（Nio）
                    DataBuffer buffer=response.bufferFactory().wrap(json.getBytes());
                    //实现拦截，同时返回结果
                    return response.writeWith(Mono.just(buffer));
                }
            }else{
                //16.请求是静态资源
                return chain.filter(exchange);
            }
        }else{
            //17.当前的请求不是签到服务，所以放行请求
            return chain.filter(exchange);
        }
    }

    //过滤器的优先级，数字越大，优先级越低
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}
